using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Drawing2D;
using AForge.Imaging.Filters;
using System.Drawing.Imaging;

namespace PBR.Filters
{
    public class Composite
    {
        /// <summary>
        /// Composites the overImage onto the underImage
        /// </summary>
        /// <param name="underImage"></param>
        /// <param name="overImage"></param>
        /// <returns></returns>
        public void ApplyInPlace(Bitmap underImage, Bitmap overImage)
        {
            if (underImage.PixelFormat != PixelFormat.Format8bppIndexed || overImage.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new ArgumentException("Composite Apply takes one BW and one RGBA images");
            }
            BitmapData underImageData = underImage.LockBits(
                new Rectangle(0, 0, underImage.Width, underImage.Height),
                ImageLockMode.ReadWrite, underImage.PixelFormat);

            BitmapData overImageData = overImage.LockBits(
                new Rectangle(0, 0, overImage.Width, overImage.Height),
                ImageLockMode.ReadOnly, overImage.PixelFormat);

            ProcessFilter(underImageData, overImageData);

            // unlock destination images
            underImage.UnlockBits(underImageData);
            overImage.UnlockBits(overImageData);
        }

        private unsafe void ProcessFilter(BitmapData underData, BitmapData overData)
        {
			// get width and height
            int width = underData.Width;
            int height = underData.Height;

            int underOffset = underData.Stride - width;
            int overOffset = overData.Stride - width * 4;

			// do the job
			byte* underPtr = (byte *) underData.Scan0.ToPointer();
            byte* overPtr = (byte*) overData.Scan0.ToPointer();

			// for each line
			for ( int y = 0; y < height; y++ )
			{
				// for each pixel
                for (int x = 0; x < width; x++, underPtr += 1, overPtr += 4)
				{
                    (*underPtr) = (byte)(((*underPtr) * (255 - overPtr[AForge.Imaging.RGBA.A]) +
                        overPtr[AForge.Imaging.RGBA.R] * overPtr[AForge.Imaging.RGBA.A]) / 255);
				}
                underPtr += underOffset;
                overPtr += overOffset;
			}
		}
    }
}

